#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
C服务器测试脚本: 健康检查机制 (场景2.1-2.5)
测试C服务器对G服务器的健康检查机制
"""

import requests
import json
import time
import sys
import os
import threading
from typing import Dict, Any, List

# 添加项目根目录到Python路径
sys.path.append(os.path.join(os.path.dirname(__file__), '../../1-gateway/02-api-gateway'))

class HealthCheckTester:
    """健康检查测试类"""
    
    def __init__(self):
        self.gateway_url = "https://www.gongjuxiang.work"
        self.webhook_url = f"{self.gateway_url}/webhook/register"
        self.backend_servers_file = "../../1-gateway/02-api-gateway/backend_servers.json"
        self.correct_secret = "gpu-server-register-to-api-gateway-2024"
        self.g_server_ip = "10.5.0.191"
        self.g_server_port = 5800
        self.health_check_interval = 3  # 健康检查间隔
        
    def load_backend_servers(self) -> list:
        """加载backend_servers.json"""
        try:
            with open(self.backend_servers_file, 'r', encoding='utf-8') as f:
                return json.load(f)
        except Exception as e:
            print(f"❌ 加载backend_servers.json失败: {e}")
            return []
    
    def save_backend_servers(self, servers: list):
        """保存backend_servers.json"""
        try:
            with open(self.backend_servers_file, 'w', encoding='utf-8') as f:
                json.dump(servers, f, indent=2, ensure_ascii=False)
            print(f"✅ backend_servers.json已保存: {len(servers)}个服务器")
        except Exception as e:
            print(f"❌ 保存backend_servers.json失败: {e}")
    
    def setup_g_server(self):
        """设置G服务器注册到C"""
        print("🔧 设置G服务器注册...")
        
        register_data = {
            "internal_ip": self.g_server_ip,
            "public_ip": "140.143.155.42",
            "region": "ap-beijing",
            "port": self.g_server_port,
            "secret": self.correct_secret
        }
        
        try:
            response = requests.post(self.webhook_url, json=register_data, timeout=10)
            if response.status_code == 200:
                result = response.json()
                print(f"✅ G服务器注册成功: {result.get('server_id', '')}")
                return True
            else:
                print(f"❌ G服务器注册失败: {response.status_code}")
                return False
        except Exception as e:
            print(f"❌ G服务器注册异常: {e}")
            return False
    
    def check_g_server_health(self) -> tuple[bool, str]:
        """检查G服务器健康状态"""
        try:
            health_url = f"http://{self.g_server_ip}:{self.g_server_port}/health"
            response = requests.get(health_url, timeout=5)
            if response.status_code == 200:
                return True, "healthy"
            else:
                return False, f"HTTP {response.status_code}"
        except requests.exceptions.Timeout:
            return False, "timeout"
        except requests.exceptions.ConnectionError:
            return False, "connection_error"
        except Exception as e:
            return False, str(e)
    
    def wait_for_health_check(self, expected_count: int, timeout: int = 30):
        """等待健康检查执行指定次数"""
        print(f"⏳ 等待健康检查执行{expected_count}次...")
        
        start_time = time.time()
        check_count = 0
        
        while time.time() - start_time < timeout:
            servers = self.load_backend_servers()
            if servers:
                # 检查是否有服务器记录更新
                server = servers[0]
                last_check = server.get('last_check_time', '')
                
                # 如果last_check_time发生变化，说明健康检查在执行
                if last_check:
                    check_count += 1
                    if check_count >= expected_count:
                        print(f"✅ 健康检查已执行{expected_count}次")
                        return True
                
            time.sleep(1)
        
        print(f"⏰ 等待超时，健康检查可能未正常执行")
        return False
    
    def get_server_status(self) -> Dict[str, Any]:
        """获取服务器状态"""
        servers = self.load_backend_servers()
        if servers:
            return servers[0]
        return {}
    
    def test_scenario_2_1(self):
        """场景2.1: G正常响应健康检查"""
        print("\n" + "="*60)
        print("🧪 场景2.1: G正常响应健康检查")
        print("="*60)
        
        # 确保G服务器已注册
        if not self.setup_g_server():
            return False
        
        # 等待健康检查执行
        time.sleep(5)  # 等待健康检查启动
        
        # 检查G服务器是否健康
        is_healthy, status = self.check_g_server_health()
        
        if is_healthy:
            print("✅ G服务器健康检查正常")
            
            # 验证backend_servers.json中的状态
            server_status = self.get_server_status()
            if server_status:
                if server_status.get('is_healthy', False):
                    print("✅ backend_servers.json中标记为健康")
                    print(f"   - fail_count: {server_status.get('fail_count', 0)}")
                    print(f"   - is_healthy: {server_status.get('is_healthy', False)}")
                    print("✅ 场景2.1测试通过")
                    return True
                else:
                    print("❌ backend_servers.json中未标记为健康")
                    return False
            else:
                print("❌ 无法获取服务器状态")
                return False
        else:
            print(f"❌ G服务器健康检查失败: {status}")
            return False
    
    def test_scenario_2_2(self):
        """场景2.2: G健康检查超时/失败"""
        print("\n" + "="*60)
        print("🧪 场景2.2: G健康检查超时/失败")
        print("="*60)
        
        # 确保G服务器已注册
        if not self.setup_g_server():
            return False
        
        print("⚠️ 注意：此测试需要G服务器停止服务")
        print("请手动停止G服务器，然后按Enter继续...")
        input()
        
        # 等待健康检查执行多次
        time.sleep(10)  # 等待多次健康检查
        
        # 检查服务器状态
        server_status = self.get_server_status()
        if server_status:
            fail_count = server_status.get('fail_count', 0)
            is_healthy = server_status.get('is_healthy', True)
            
            print(f"📊 服务器状态:")
            print(f"   - fail_count: {fail_count}")
            print(f"   - is_healthy: {is_healthy}")
            
            if fail_count > 0:
                print("✅ 健康检查失败次数已增加")
                print("✅ 场景2.2测试通过")
                return True
            else:
                print("❌ 健康检查失败次数未增加")
                return False
        else:
            print("❌ 无法获取服务器状态")
            return False
    
    def test_scenario_2_3(self):
        """场景2.3: G失败1次后自动标记不可用"""
        print("\n" + "="*60)
        print("🧪 场景2.3: G失败1次后自动标记不可用")
        print("="*60)
        
        # 确保G服务器已注册且健康
        if not self.setup_g_server():
            return False
        
        print("⚠️ 注意：此测试需要G服务器停止服务")
        print("请手动停止G服务器，然后按Enter继续...")
        input()
        
        # 等待健康检查执行
        time.sleep(8)  # 等待健康检查执行
        
        # 检查服务器状态
        server_status = self.get_server_status()
        if server_status:
            fail_count = server_status.get('fail_count', 0)
            is_healthy = server_status.get('is_healthy', True)
            
            print(f"📊 服务器状态:")
            print(f"   - fail_count: {fail_count}")
            print(f"   - is_healthy: {is_healthy}")
            
            # 验证fail_count >= 1 且 is_healthy = False
            if fail_count >= 1 and not is_healthy:
                print("✅ 服务器已标记为不可用")
                print("✅ 场景2.3测试通过")
                return True
            else:
                print("❌ 服务器未正确标记为不可用")
                print(f"   期望: fail_count >= 1, is_healthy = False")
                print(f"   实际: fail_count = {fail_count}, is_healthy = {is_healthy}")
                return False
        else:
            print("❌ 无法获取服务器状态")
            return False
    
    def test_scenario_2_4(self):
        """场景2.4: G失败2次后自动删除记录"""
        print("\n" + "="*60)
        print("🧪 场景2.4: G失败2次后自动删除记录")
        print("="*60)
        
        # 确保G服务器已注册
        if not self.setup_g_server():
            return False
        
        print("⚠️ 注意：此测试需要G服务器停止服务")
        print("请确保G服务器已停止，然后按Enter继续...")
        input()
        
        # 等待健康检查执行多次（fail_count达到2）
        print("⏳ 等待健康检查执行多次，直到自动删除...")
        
        # 监控服务器记录
        start_time = time.time()
        timeout = 60  # 60秒超时
        
        while time.time() - start_time < timeout:
            servers = self.load_backend_servers()
            server_count = len(servers)
            
            if server_count == 0:
                print("✅ 服务器记录已自动删除")
                print("✅ 场景2.4测试通过")
                return True
            elif servers:
                server = servers[0]
                fail_count = server.get('fail_count', 0)
                print(f"📊 当前状态: fail_count = {fail_count}, 服务器数量 = {server_count}")
            
            time.sleep(2)
        
        print("⏰ 等待超时，服务器记录未被自动删除")
        return False
    
    def test_scenario_2_5(self):
        """场景2.5: G从不健康恢复为健康"""
        print("\n" + "="*60)
        print("🧪 场景2.5: G从不健康恢复为健康")
        print("="*60)
        
        # 确保G服务器已注册
        if not self.setup_g_server():
            return False
        
        print("⚠️ 注意：此测试需要G服务器重启服务")
        print("请先停止G服务器，然后重启，最后按Enter继续...")
        input()
        
        # 等待健康检查执行
        time.sleep(8)  # 等待健康检查执行
        
        # 检查G服务器健康状态
        is_healthy, status = self.check_g_server_health()
        
        if is_healthy:
            print("✅ G服务器健康检查正常")
            
            # 验证backend_servers.json中的状态
            server_status = self.get_server_status()
            if server_status:
                fail_count = server_status.get('fail_count', 0)
                is_healthy_status = server_status.get('is_healthy', False)
                
                print(f"📊 服务器状态:")
                print(f"   - fail_count: {fail_count}")
                print(f"   - is_healthy: {is_healthy_status}")
                
                # 验证恢复为健康状态
                if is_healthy_status and fail_count == 0:
                    print("✅ 服务器已恢复为健康状态")
                    print("✅ 场景2.5测试通过")
                    return True
                else:
                    print("❌ 服务器未正确恢复为健康状态")
                    return False
            else:
                print("❌ 无法获取服务器状态")
                return False
        else:
            print(f"❌ G服务器健康检查失败: {status}")
            return False
    
    def run_all_tests(self):
        """运行所有健康检查场景测试"""
        print("🚀 开始健康检查机制测试")
        print(f"🌐 网关URL: {self.gateway_url}")
        print(f"🖥️ G服务器: {self.g_server_ip}:{self.g_server_port}")
        print(f"⏱️ 健康检查间隔: {self.health_check_interval}秒")
        
        tests = [
            ("场景2.1", self.test_scenario_2_1),
            ("场景2.2", self.test_scenario_2_2),
            ("场景2.3", self.test_scenario_2_3),
            ("场景2.4", self.test_scenario_2_4),
            ("场景2.5", self.test_scenario_2_5)
        ]
        
        results = []
        for test_name, test_func in tests:
            try:
                print(f"\n🔄 开始执行 {test_name}...")
                result = test_func()
                results.append((test_name, result))
                
                if not result:
                    print(f"⚠️ {test_name} 测试失败，是否继续？(y/n)")
                    if input().lower() != 'y':
                        break
                        
            except Exception as e:
                print(f"❌ {test_name}测试异常: {e}")
                results.append((test_name, False))
        
        # 输出测试结果
        print("\n" + "="*60)
        print("📊 测试结果汇总")
        print("="*60)
        
        passed = 0
        for test_name, result in results:
            status = "✅ 通过" if result else "❌ 失败"
            print(f"{test_name}: {status}")
            if result:
                passed += 1
        
        print(f"\n📈 总体结果: {passed}/{len(results)} 个测试通过")
        
        if passed == len(results):
            print("🎉 所有健康检查场景测试通过！")
            return True
        else:
            print("⚠️ 部分测试失败，请检查相关配置")
            return False

def main():
    """主函数"""
    print("🧪 C服务器测试脚本: 健康检查机制")
    print("测试场景: 2.1-2.5")
    print("-" * 60)
    
    tester = HealthCheckTester()
    success = tester.run_all_tests()
    
    if success:
        print("\n✅ 所有测试完成，结果正常")
        sys.exit(0)
    else:
        print("\n❌ 测试失败，请检查配置")
        sys.exit(1)

if __name__ == "__main__":
    main()
